package com.sqtracker.recommender.strategy;

import com.sqtracker.recommender.dto.RecommendationResponse;
import com.sqtracker.recommender.util.VectorUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 最大边缘相关性(MMR)策略
 * 用于平衡推荐结果的相关性和多样性
 */
@Component
public class MMRDiversityStrategy {

    @Value("${recommendation.mmr.lambda:0.7}")
    private double lambda; // 权衡相关性和多样性的参数 (0.0-1.0)

    /**
     * 使用MMR算法对推荐结果进行多样化处理
     * MMR = λ * Rel(i) - (1-λ) * max(Sim(i,j))
     *
     * @param response 原始推荐响应
     * @return 多样化后的推荐响应
     */
    public RecommendationResponse diversify(RecommendationResponse response) {
        List<Map<String, Object>> originalRecs = response.getRecommendations();

        if (originalRecs == null || originalRecs.size() <= 1) {
            return response;
        }

        // 保留原始推荐的数量
        int totalCount = originalRecs.size();

        // 1. 计算每个推荐项的特征向量
        Map<String, Map<String, Double>> itemVectors = new HashMap<>();
        Map<String, Map<String, Object>> itemsMap = new HashMap<>();

        for (Map<String, Object> rec : originalRecs) {
            String torrentId = (String) rec.get("torrentId");
            Map<String, Double> vector = extractFeatureVector(rec);

            itemVectors.put(torrentId, vector);
            itemsMap.put(torrentId, rec);
        }

        // 2. 应用MMR算法
        List<String> selectedIds = new ArrayList<>();
        List<String> candidateIds = new ArrayList<>(itemsMap.keySet());

        // 选择相关性最高的项作为起始项
        candidateIds.sort((id1, id2) -> {
            Double score1 = (Double) itemsMap.get(id1).get("score");
            Double score2 = (Double) itemsMap.get(id2).get("score");
            return Double.compare(score2, score1); // 降序
        });

        // 添加第一个项目
        selectedIds.add(candidateIds.get(0));
        candidateIds.remove(0);

        // 迭代选择剩余项目
        while (!candidateIds.isEmpty() && selectedIds.size() < totalCount) {
            double maxMMR = Double.NEGATIVE_INFINITY;
            String nextBestId = null;

            for (String candidateId : candidateIds) {
                // 计算相关性
                double relevance = (Double) itemsMap.get(candidateId).get("score");

                // 计算与已选项的最大相似度
                double maxSimilarity = 0.0;
                for (String selectedId : selectedIds) {
                    double similarity = VectorUtil.cosineSimilarity(
                            itemVectors.get(candidateId),
                            itemVectors.get(selectedId));

                    maxSimilarity = Math.max(maxSimilarity, similarity);
                }

                // 计算MMR值
                double mmr = lambda * relevance - (1 - lambda) * maxSimilarity;

                // 更新最大MMR
                if (mmr > maxMMR) {
                    maxMMR = mmr;
                    nextBestId = candidateId;
                }
            }

            // 添加MMR最大的项目
            if (nextBestId != null) {
                selectedIds.add(nextBestId);
                candidateIds.remove(nextBestId);
            } else {
                break;
            }
        }

        // 3. 构建多样化后的推荐列表
        List<Map<String, Object>> diversifiedRecs = selectedIds.stream()
                .map(itemsMap::get)
                .collect(Collectors.toList());

        // 返回多样化后的推荐响应
        RecommendationResponse diversifiedResponse = new RecommendationResponse();
        diversifiedResponse.setRecommendations(diversifiedRecs);
        diversifiedResponse.setRequestId(response.getRequestId());
        diversifiedResponse.setTimestamp(response.getTimestamp());
        diversifiedResponse.setMeta(response.getMeta());

        return diversifiedResponse;
    }

    /**
     * 从推荐项中提取特征向量
     */
    private Map<String, Double> extractFeatureVector(Map<String, Object> item) {
        Map<String, Double> vector = new HashMap<>();

        // 提取算法类型作为特征
        String algorithm = (String) item.get("algorithm");
        if (algorithm != null) {
            for (String algo : algorithm.split(",")) {
                vector.put("algo_" + algo.trim(), 1.0);
            }
        }

        // 提取推荐理由作为特征
        String reason = (String) item.get("reason");
        if (reason != null) {
            for (String r : reason.split(";")) {
                vector.put("reason_" + r.trim(), 1.0);
            }
        }

        // 添加额外特征
        vector.put("score", (Double) item.get("score"));

        // 如果有元数据，可以进一步添加特征
        if (item.containsKey("metadata") && item.get("metadata") instanceof Map) {
            Map<String, Object> metadata = (Map<String, Object>) item.get("metadata");

            if (metadata.containsKey("category")) {
                vector.put("category_" + metadata.get("category"), 1.0);
            }

            if (metadata.containsKey("language")) {
                vector.put("language_" + metadata.get("language"), 1.0);
            }

            if (metadata.containsKey("quality")) {
                vector.put("quality_" + metadata.get("quality"), 1.0);
            }
        }

        return vector;
    }
}